import uvicorn
import threading
import signal
import sys
from fastapi import FastAPI
from pydantic import BaseModel
from concurrent.futures import ThreadPoolExecutor
import time

import douban_passive_fetch
import douban_positive_fetch

from setting import *
# from tools import getCurTime
from util.data_utils import getCurTime

#from util.logs_utils import *

app = FastAPI()

# 全局变量用于控制程序退出
running = True

# 数据模型
class Item(BaseModel):
    url: str|None
    group_name: str|None
    push_task_id: int|None
    
    
    
class Item2(BaseModel):
    id: str|None
    
@app.post("/receive_url")
def receive_url_handler(item: Item):
    # 判断是否含有Url
    if item.url is None or item.group_name is None:
        return {"code": 400,"receive_time":getCurTime(),"data":{},"message": "url and group_name is required"}
    try:
        Q.put((item.group_name,item.url,item.push_task_id))
        return {"code": 200,"receive_time":getCurTime(),"data": f"push task to queue success. current task count: {Q.qsize()}"}
    except Exception as e:
        return {"code": 500,"receive_time":getCurTime(),"data":{},"message": f"error: {e}"}
    
    
@app.post("/is_filter")
def is_filter(item: Item2):
    # 判断是否含有Url
    if item.id is None:
        return {"code": 400,"time":getCurTime(),"message": "id is required"}
    try:
        return {"code": 200,"time":getCurTime(),"status": R.sismember("unique_set_douban",item.id)}
    except Exception as e:
        return {"code": 500,"time":getCurTime(),"message": f"error: {e}"}

def safe_run(target, *args, **kwargs):
    """安全运行函数，包含异常处理"""
    try:
        target(*args, **kwargs)
    except Exception as e:
        print(f"{getCurTime()} Thread error in {target.__name__}: {e}")
        #logger.info(f"Thread error in {target.__name__}: {e}")
        import traceback
        traceback.print_exc()

def signal_handler(signum, frame):
    """信号处理器，用于优雅关闭"""
    global running
    print(f"{getCurTime()} 收到退出信号，正在关闭服务...")
    #logger.info(f"收到退出信号，正在关闭服务...")

    running = False
    sys.exit(0)

def run_uvicorn():
    """运行uvicorn服务器"""
    uvicorn.run(app, host="0.0.0.0", port=4130)


def run_passive_fetch():
    """运行被动抓取任务"""
    douban_passive_fetch.main()

def run_positive_fetch_buy():
    """运行买组主动抓取任务"""
    douban_positive_fetch.main("https://www.douban.com/group/698716/?tab=51757", "买组")

def run_positive_fetch_pin():
    """运行拼组主动抓取任务"""
    douban_positive_fetch.main("https://www.douban.com/group/536786/?tab=47726", "拼组")

def main():
    # 注册信号处理器
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    
    print(f"{getCurTime()} 启动豆瓣数据采集服务...")
    #logger.info(f" 启动豆瓣数据采集服务...")
    
    # 使用ThreadPoolExecutor管理线程
    with ThreadPoolExecutor(max_workers=4, thread_name_prefix="DoubanWorker") as executor:
        try:
            time.sleep(5)
            # 提交所有任务
            futures = [
                executor.submit(safe_run, run_uvicorn),
                executor.submit(safe_run, run_passive_fetch),
                executor.submit(safe_run, run_positive_fetch_buy),
                executor.submit(safe_run, run_positive_fetch_pin)
            ]
            
            print(f"{getCurTime()} 所有服务已启动")
            #logger.info(f" 所有服务已启动...")
            
            # 等待所有任务完成（实际上它们会一直运行）
            for future in futures:
                try:
                    future.result()  # 这里会阻塞直到任务完成或异常
                except Exception as e:
                    print(f"{getCurTime()} 任务执行异常: {e}")
                    #logger.info(f" 任务执行异常: {e}")
                    
        except KeyboardInterrupt:
            print(f"{getCurTime()} 收到键盘中断，正在关闭...")
            #logger.info(f" 收到键盘中断，正在关闭...")
        except Exception as e:
            print(f"{getCurTime()} 主程序异常: {e}")
            #logger.info(f" 主程序异常: {e}")
        finally:
            print(f"{getCurTime()} 正在关闭所有服务...")
            #logger.info(f" 正在关闭所有服务...")
            # ThreadPoolExecutor会自动等待所有线程完成

if __name__ == "__main__":
    main()
